package com.itheima.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.common.R;
import com.itheima.dto.DishDTO;
import com.itheima.pojo.Category;
import com.itheima.pojo.Dish;
import com.itheima.pojo.DishFlavor;
import com.itheima.service.CategoryService;
import com.itheima.service.DishFlavorService;
import com.itheima.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.itheima.common.R.success;

/*菜品*/
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private DishFlavorService dishFlavorService;
    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
     * <p>Description: 添加菜品</p>
     * 
     * @author liuyiming
     * @date 2022-10-10 10:10
     * @version 1.0.0
     */
    @PostMapping
    //再添加、删除、修改的时候，需要对redis中的数据进行删除操作
    @CacheEvict(value = "dishCache", allEntries = true)
    public R<String> save(@RequestBody DishDTO dishDTO){
        log.info("添加菜品{}",dishDTO);
        dishService.saveDish(dishDTO);
        //清理所有菜品的缓存数据
        redisTemplate.delete(redisTemplate.keys("dish_*"));
        return R.success("添加菜品成功");
    }

    /**
     * <p>Description: 菜品信息分页查询</p>
     *
     * @author liuyiming
     * @date 2022-10-10 14:05
     * @version 1.0.0
     */
    @GetMapping("/page")
    // 先查询redis，查询到了就直接返回
    // 如果redis中没查询到则查询数据库，并推数据到redis，并返回
    @Cacheable(value = "dishCache")
    public R<Page> page(int page, int pageSize,String name) {
        log.info("菜品信息分页查询page={},pageSize={},name={}", page, pageSize,name);
        //1.创建Dish和DishDTO的分页构造器
        Page<Dish> dishPage = new Page<>(page,pageSize);
        //2.组装条件查询（模糊查询name、updatetime倒序排序）
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.like(name!=null,Dish::getName,name);
        dishLambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);
        //3.开始查询Dish
        dishService.page(dishPage,dishLambdaQueryWrapper);

        //4.查询出来所有菜品的基本数据
        List<Dish> records = dishPage.getRecords();
        //5.开始查询所有的分类信息
        //  1.先把所有菜品的分类ID查询出来，放入Set（因为Set会自动去重）
        /*Set<Long> categoryIds = records.stream().map(item -> item.getCategoryId()).collect(Collectors.toSet());*/
        Set<Long> categoryIds = new HashSet<>();
        for (Dish dish : records) {
            categoryIds.add(dish.getCategoryId());
        }
        //  2.开始查询分类信息
        List<Category> categories = categoryService.listByIds(categoryIds);
        //6.把查询出的分类的信息，存入一个Map中，id为key，name为value
        /*Map<Long, String> categoryMap = categories.stream().collect(Collectors.toMap(Category::getId, Category::getName));*/
        Map<Long, String> categoryMap = new HashMap<>();
        for (Category category : categories) {
            categoryMap.put(category.getId(), category.getName());
        }
        //7.循环遍历categoryMap,给查出的菜品基本数据赋值
        for (Dish dish : records) {
            dish.setCategoryName(categoryMap.get(dish.getCategoryId()));
        }
        dishPage.setRecords(records);

        /*
        //注意：
        //    BeanUtils的copy底层是用反射形式复制的，或忽略泛型规范，所以在复制到dishDTOPage中的时候，records是Dish类型的
        //    这时候再对dishDTOPage的records遍历，泛型规范的是DishDTO，而取出来的是Dish类型的，就会报错Dish cannot be cast to DishDTO
        BeanUtils.copyProperties(dishPage,dishDTOPage);
        for (DishDTO record : dishDTOPage.getRecords()) {
            Category category = categoryService.getById(record.getCategoryId());
            record.setCategoryName(category.getName());
        }*/

        //8.返回DTO
        return R.success(dishPage);
    }

    /**
     * <p>Description: 根据ID查询菜品具体信息</p>
     *
     * @author liuyiming
     * @date 2022-10-10 19:04
     * @version 1.0.0
     */
    @GetMapping("/{id}")
    @Cacheable(value = "dishCache")
    public R<DishDTO> queryDishById(@PathVariable String id) {
        log.info("根据ID查询菜品具体信息");
        DishDTO dishDTO = dishService.queryDishInfo(id);
        return R.success(dishDTO);
    }
    
    /**
     * <p>Description: 修改菜品具体信息</p>
     * 
     * @author liuyiming
     * @date 2022-10-10 19:51
     * @version 1.0.0
     */
    @PutMapping
    @CacheEvict(value = "dishCache", allEntries = true)
    public R<String> updateById(@RequestBody DishDTO dishDTO){
        log.info("根据ID修改菜品具体信息");
        dishService.updateDishInfoById(dishDTO);
        //清理所有菜品的缓存数据
        redisTemplate.delete(redisTemplate.keys("dish_*"));
        return R.success("修改菜品成功");
    }
    
    /**
     * <p>Description: 根据条件查询菜品信息</p>
     * 
     * @author liuyiming
     * @date 2022-10-12 11:44
     * @version 1.0.0
     */
    /*@GetMapping("/list")
    public R<List<Dish>> list(Dish dish){
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        dishLambdaQueryWrapper.orderByAsc(Dish::getSort);
        dishLambdaQueryWrapper.eq(Dish::getStatus,1);
        List<Dish> list = dishService.list(dishLambdaQueryWrapper);
        return R.success(list);
    }*/
    @GetMapping("/list")
    @Cacheable(value = "dishCache")
    public R<List<DishDTO>> list(Dish dish){
        List<DishDTO> dishDTOS = null;
        //先从redis中获取
        //组装key
        String key = "dish_"+dish.getCategoryId()+"_"+dish.getStatus();
        dishDTOS = (List<DishDTO>)redisTemplate.opsForValue().get(key);
        //如果获取到了则直接返回，无需查询数据库
        if(dishDTOS != null){
            return R.success(dishDTOS);
        }

        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        dishLambdaQueryWrapper.orderByAsc(Dish::getSort);
        dishLambdaQueryWrapper.eq(Dish::getStatus,1);
        List<Dish> list = dishService.list(dishLambdaQueryWrapper);

        dishDTOS = new ArrayList<>();
        for (Dish item : list) {
            DishDTO dishDTO = new DishDTO();
            BeanUtils.copyProperties(item,dishDTO);

            //根据菜品id查询口味表信息
            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<DishFlavor>();
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId,item.getId());
            List<DishFlavor> dishFlavorList = dishFlavorService.list(dishFlavorLambdaQueryWrapper);
            dishDTO.setFlavors(dishFlavorList);
            dishDTOS.add(dishDTO);
        }
        //如果没获取到，则查询出后推到redis
        redisTemplate.opsForValue().set(key,dishDTOS);
        return R.success(dishDTOS);
    }
    
    /**
     * <p>Description: 批量停售/起售菜品</p>
     * 
     * @author liuyiming
     * @date 2022-10-12 20:43
     * @version 1.0.0
     */
    @PostMapping("/status/{status}")
    @CacheEvict(value = "dishCache", allEntries = true)
    public R<String> updateStatus(@PathVariable Integer status, Long[] ids){
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.in(Dish::getId,ids);
        Dish dish = new Dish();
        dish.setStatus(status);
        dishService.update(dish,dishLambdaQueryWrapper);
        //清理所有菜品的缓存数据
        redisTemplate.delete(redisTemplate.keys("dish_*"));
        return R.success("状态修改成功");
    }

    /**
     * <p>Description: 删除菜品</p>
     *
     * @author liuyiming
     * @date 2022-10-20 15:39
     * @version 1.0.0
     */
    @DeleteMapping
    @Transactional
    @CacheEvict(value = "dishCache", allEntries = true)
    public R<String> delete(@RequestParam List<Long> ids){
        log.info("逻辑删除菜品");
        dishService.removeByIds(ids);
        LambdaUpdateWrapper<DishFlavor> dishFlavorLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        dishFlavorLambdaUpdateWrapper.in(DishFlavor::getDishId,ids);
        dishFlavorService.remove(dishFlavorLambdaUpdateWrapper);
        //清理所有菜品的缓存数据
        redisTemplate.delete(redisTemplate.keys("dish_*"));
        return R.success("删除成功");
    }

    
    
}
